# webpack4 环境搭建
30 秒速记
- 目标:把
JSX、ES6+、Less编译成浏览器能直接跑的JS和CSS - 配置拆三份:
base放共用的入口、loader、插件,dev和prod用webpack-merge只写差异 Webpack 4起要写mode,不写会警告并按production处理- 构建命令写进
package.json的scripts,依赖装在项目里,别靠全局webpack Webpack 4已不再维护,新项目直接上Webpack 5或Vite,老项目按官方迁移指南升级
搭 Webpack 环境其实就是告诉它三件事:从哪个文件开始打包、遇到什么类型的文件用什么 loader 转换、最后输出到哪。 这个项目要编译 React 的 JSX、ES6+ 语法和 Less 样式,所以核心是 babel-loader 加一组样式 loader。配置我会拆成基础、开发、生产三份,开发要 source map 好调试,生产要压缩。另外说一句,Webpack 4 是 2018 年的版本,现在已经停止维护,学它的概念没问题,新项目我会直接用 Webpack 5 或者 Vite。
理解「webpack4 环境搭建」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。
工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。
Webpack 可以理解成一个「翻译 + 打包」工具:它从入口文件出发,顺着 import / require 把依赖全部找出来,每种文件交给对应的 loader 翻译,最后合成几个浏览器能直接加载的文件。
这个项目的需求是:React 页面用 JSX 写、样式用 Less、组件库用 antd,所以需要的依赖大致是:
npm i -D webpack@4 webpack-cli@3 webpack-merge \
babel-loader @babel/core @babel/preset-env @babel/preset-react \
css-loader less less-loader postcss-loader mini-css-extract-plugin
npm i react react-dom antd
package.json 里把命令固定下来:
{
"scripts": {
"dev": "webpack --config static/build/webpack.dev.config.js --watch",
"build": "webpack --config static/build/webpack.prod.config.js"
}
}
配置拆成三份:webpack.base.config.js 写入口、输出、loader 这些共用部分;开发配置加 mode: 'development' 和 devtool: 'source-map';生产配置加 mode: 'production' 和压缩。开发和生产都通过 webpack-merge 继承基础配置,公共部分只改一处。
版本上要有数:Webpack 5 在 2020 年发布,Webpack 4 已经不再维护,很多 loader 的新版本也不再支持它。照着教程学概念没问题,真开新项目建议直接用 Webpack 5 或 Vite。
面试官追问
追问 1不写 mode 会怎样?
Webpack 4 会给一个警告,然后按 production 处理,开发时打出来的代码是压缩过的,调试很痛苦。开发配置里显式写 mode: 'development',process.env.NODE_ENV 也会自动跟着设好。
追问 2为什么不建议用全局安装的 webpack?
每台机器装的版本可能不一样,CI 上也不一定有,换台机器就跑不起来。装成项目的 devDependencies,命令写进 scripts,npm run build 用的就是 node_modules/.bin 里那个版本。
追问 3老项目还在 Webpack 4,升到 5 最容易踩哪些坑?
Node 核心模块的 polyfill 没了,用到 Buffer、process 的要自己配 resolve.fallback;file-loader、url-loader 被内置的 asset modules 替代;一些插件要升大版本。按官方迁移指南一项项过,比一口气全升稳。
追问 4构建在 CI 上失败了,流水线却显示成功,可能是什么原因?
多半是外层脚本把退出码吞了,比如 webpack || true,或者用 & 放后台跑。webpack 编译出错会以非零码退出,直接跑底层命令看 echo $? 就能确认。
# webpack4 环境搭建
# 前言
30 秒速记
- 浏览器不认识
JSX,老浏览器也不认识部分ES6+语法,必须先编译 Babel负责翻译语法,Webpack负责把散落的模块打成几个文件,还能压缩混淆- 后端
Koa只负责返回页面和静态资源,页面里引用的是编译产物,不是源码 - 编译只转语法,
Promise、Array.prototype.includes这类新API要靠polyfill - 密钥别通过
DefinePlugin写进前端包,打进去就等于公开了
这个项目的页面用 React 写,JSX 浏览器看不懂,所以要用 Webpack 配合 Babel 把源码编译成普通 JS,顺便压缩。 你可以把它想成一个翻译加打包的过程:Babel 把 <App /> 翻成 React.createElement(App),把新语法降级;Webpack 顺着 import 把几十个文件合并成几个包,再压缩体积。Koa 那边只管返回 HTML 和这些打包好的文件。要注意编译只解决语法问题,新 API 在老浏览器里还是要 polyfill。
由于demos/project 前端渲染是通过react.js渲染的,这就需要webpack4 对react.js及其相关JSX,ES6/7代码进行编译和混淆压缩。
面试官追问
追问 1浏览器直接引入带 JSX 的文件会怎样?
解析到 < 就报 SyntaxError: Unexpected token '<',整个脚本不执行,页面白屏。必须先编译,页面引用 output/dist 里的产物。
追问 2Babel 编译过了,IE 里还是报 Promise is undefined,为什么?
Babel 默认只转语法,Promise 是运行时 API,不会凭空变出来。要用 @babel/preset-env 配 useBuiltIns: 'usage' 加 core-js,按需注入 polyfill。
追问 3开发环境要不要也压缩?
不用。开发阶段要的是快和好调试,压缩会拖慢构建,报错堆栈也看不懂。压缩只放在生产配置里,开发配 source map。
追问 4能不能把接口密钥用 DefinePlugin 注入到前端代码里?
不能。DefinePlugin 是在编译时做文本替换,值会原样写进 bundle,任何人打开 DevTools 都能看到。前端只放公开配置,密钥留在 Koa 服务端。
# webpack4
30 秒速记
- 四个核心概念:
entry入口、output输出、loader转换非JS文件、plugin干loader干不了的事 Webpack 4引入mode:development不压缩、构建快,production自动压缩和tree shakingCommonsChunkPlugin被optimization.splitChunks取代,第三方库抽成vendor包Webpack 4内置压缩器是terser-webpack-plugin;uglifyjs-webpack-plugin不支持ES6+语法- 构建前清空输出目录,否则旧文件留着会掩盖「这次其实没生成」的问题
Webpack 4 的配置就围绕四个东西:entry 从哪开始、output 输出到哪、loader 怎么转换各种文件、plugin 做额外处理。 它相对 Webpack 3 最大的变化是加了 mode,选 production 就自动帮你压缩、定义 NODE_ENV、开 tree shaking,很多以前要手配的插件都省了。还有拆包从 CommonsChunkPlugin 换成了 splitChunks。压缩这块现在默认用 terser,老教程里的 uglifyjs-webpack-plugin 碰到 const、箭头函数这类 ES6 代码会报错,没有特殊原因就别再用。
理解「webpack4 」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。
工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。
Webpack 的配置看起来很多,拆开就四块:
module.exports = {
mode: 